home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / prog / plane / seg_int.c < prev    next >
C/C++ Source or Header  |  1994-08-05  |  15KB  |  633 lines

  1. #include <LEDA/sweep_segments.h>
  2.  
  3. #include <LEDA/segment.h>
  4. #include <LEDA/graph.h>
  5. #include <LEDA/prio.h>
  6.  
  7. #include <LEDA/sortseq.h>
  8. #include <LEDA/impl/skiplist.h>
  9. #include <LEDA/impl/ab_tree.h>
  10.  
  11. #include <math.h>
  12.  
  13.  
  14. #define EPS  0.00001
  15. #define EPS2 0.0000000001
  16.  
  17. class sw_POINT;
  18. class sw_SEGMENT;
  19. typedef sw_POINT* sw_point;
  20. typedef sw_SEGMENT* sw_segment;
  21.  
  22. enum sw_point_type {Cross=0,Rightend=1,Leftend=2}; 
  23.  
  24. class sw_POINT
  25. {
  26.   friend class sw_SEGMENT;
  27.  
  28.   sw_segment seg;
  29.   int     kind;
  30.   double  x;
  31.   double  y;
  32.  
  33.   public:
  34.  
  35.   sw_POINT(double a,double b)  
  36.   { 
  37.     x=a; y=b; seg=0; kind=Cross;
  38.    }
  39.  
  40.  
  41.  
  42.   sw_POINT(point p)         
  43.   { 
  44.     x=p.xcoord();y=p.ycoord();seg=0;kind=Cross;
  45.    }
  46.  
  47.  
  48.   LEDA_MEMORY(sw_POINT);
  49.  
  50.   friend double     get_x(sw_point p);
  51.   friend double     get_y(sw_point p);
  52.   friend int        get_kind(sw_point p);
  53.   friend sw_segment get_seg(sw_point p);
  54.  
  55.   friend bool intersection(sw_segment, sw_segment, sw_point&);
  56. };
  57.  
  58. inline double     get_x(sw_point p)    { return p->x; }
  59. inline double     get_y(sw_point p)    { return p->y; }
  60. inline int        get_kind(sw_point p) { return p->kind; }
  61. inline sw_segment get_seg(sw_point p)  { return p->seg; }   
  62.  
  63.  
  64.  
  65. static int compare(sw_point& p1,sw_point& p2)
  66. { if (p1==p2) return 0;
  67.  
  68.   double diffx = get_x(p1) - get_x(p2);
  69.   if (fabs(diffx) > EPS2 ) return (diffx > 0.0) ? 1 : -1;
  70.  
  71.   int    diffk = get_kind(p1)-get_kind(p2);
  72.   if (diffk != 0) return diffk;
  73.  
  74.   double diffy = get_y(p1) - get_y(p2);
  75.   if (fabs(diffy) > EPS2 ) return (diffy > 0.0) ? 1 : -1;
  76.  
  77.   return 0;
  78.  
  79. }
  80.  
  81.  
  82. class sw_SEGMENT
  83. {
  84.   sw_point startpoint;
  85.   sw_point endpoint;
  86.   double  slope;
  87.   double  yshift;
  88.   node  left_node;
  89.   int   orient;
  90.   int   color;
  91.   int   name;
  92.  
  93.  
  94.   public:
  95.  
  96.   sw_SEGMENT(sw_point, sw_point,int,int);     
  97.  
  98.  ~sw_SEGMENT() { delete startpoint; delete endpoint; }     
  99.  
  100.   LEDA_MEMORY(sw_SEGMENT);
  101.  
  102.   friend sw_point get_startpoint(sw_segment seg);
  103.   friend sw_point get_endpoint(sw_segment seg);
  104.   friend double get_slope(sw_segment seg);
  105.   friend double get_yshift(sw_segment seg);
  106.   friend int  get_orient(sw_segment seg);
  107.   friend int  get_color(sw_segment seg);
  108.   friend int  get_name(sw_segment seg);
  109.   friend node get_left_node(sw_segment seg);
  110.   friend void set_left_node(sw_segment seg, node v);
  111.  
  112.   friend bool intersection(sw_segment, sw_segment, sw_point&);
  113. };
  114.  
  115. inline sw_point get_startpoint(sw_segment seg)    { return seg->startpoint; }
  116. inline sw_point get_endpoint(sw_segment seg)      { return seg->endpoint; }
  117. inline double get_slope(sw_segment seg)           { return seg->slope; }
  118. inline double get_yshift(sw_segment seg)          { return seg->yshift; }
  119. inline int  get_orient(sw_segment seg)            { return seg->orient; }
  120. inline int  get_color(sw_segment seg)             { return seg->color; }
  121. inline int  get_name(sw_segment seg)              { return seg->name; }
  122. inline node get_left_node(sw_segment seg)         { return seg->left_node; }
  123. inline void set_left_node(sw_segment seg, node v) { seg->left_node = v; }
  124.  
  125.  
  126. sw_SEGMENT::sw_SEGMENT(sw_point p1,sw_point p2,int c, int n)    
  127.   {
  128.     left_node  = nil;
  129.     color      = c;
  130.     name       = n;
  131.  
  132.     if (compare(p1,p2) < 0)
  133.      { startpoint = p1; 
  134.        endpoint = p2; 
  135.        orient = 0;
  136.       }
  137.     else
  138.      { startpoint = p2; 
  139.        endpoint = p1; 
  140.        orient = 1;
  141.       }
  142.  
  143.     startpoint->kind = Leftend; 
  144.     endpoint->kind = Rightend; 
  145.     startpoint->seg = this; 
  146.     endpoint->seg = this;
  147.  
  148.     if (endpoint->x != startpoint->x)
  149.     {
  150.       slope = (endpoint->y - startpoint->y)/(endpoint->x - startpoint->x);
  151.       yshift = startpoint->y - slope * startpoint->x;
  152.  
  153.       startpoint->x -= EPS;
  154.       startpoint->y -= EPS * slope;
  155.       endpoint->x += EPS;
  156.       endpoint->y += EPS * slope;
  157.     }
  158.     else //vertical segment
  159.     { startpoint->y -= EPS;
  160.       endpoint->y   += EPS;
  161.      }
  162.   }
  163.  
  164.  
  165. static double x_sweep;
  166. static double y_sweep;
  167.  
  168.  
  169. static int compare(sw_segment& s1,sw_segment& s2)
  170. {
  171.   double y1 = get_slope(s1)*x_sweep+get_yshift(s1);
  172.   double y2 = get_slope(s2)*x_sweep+get_yshift(s2);
  173.  
  174.   double diff = y1-y2;
  175.  
  176.   if (fabs(diff) > EPS2) return (diff > 0.0) ? 1 : -1;
  177.  
  178.   if (get_slope(s1) == get_slope(s2)) 
  179.         return compare(get_x(get_startpoint(s1)), get_x(get_startpoint(s2)));
  180.  
  181.   if (y1 <= y_sweep+EPS2)
  182.         return compare(get_slope(s1),get_slope(s2));
  183.   else
  184.         return compare(get_slope(s2),get_slope(s1));
  185.  
  186. }
  187.  
  188.  
  189. void Print(sw_segment& x) 
  190. { sw_point s = get_startpoint(x);
  191.   sw_point e = get_endpoint(x);
  192.   cout << 
  193.     string("[(%f,%f)----(%f,%f)]",get_x(s),get_y(s), get_x(e),get_y(e));
  194. }
  195.  
  196.  
  197. static priority_queue<seq_item,sw_point>* X_structure;
  198.  
  199. static sortseq<sw_segment,pq_item>* Y_structure;
  200.  
  201.  
  202.  
  203. bool intersection(sw_segment seg1,sw_segment seg2, sw_point& inter)
  204. {
  205.   if (seg1->slope == seg2->slope)
  206.     return false;
  207.   else
  208.   {
  209.     //x-coordinate  of the intersection
  210.     double Cross_x = (seg2->yshift - seg1->yshift) / (seg1->slope - seg2->slope);
  211.  
  212.     if (Cross_x <= x_sweep) return false;
  213.  
  214.     double s1 = seg1->startpoint->x;
  215.     double s2 = seg2->startpoint->x;
  216.     double e1 = seg1->endpoint->x;
  217.     double e2 = seg2->endpoint->x;
  218.  
  219.     if (s2>Cross_x || s1>Cross_x || Cross_x>e1 || Cross_x>e2) return false;
  220.  
  221.     //y-coordinate of the intersection
  222.     double Cross_y = (seg1->slope * Cross_x + seg1->yshift);
  223.     inter =  new sw_POINT(Cross_x,Cross_y);
  224.  
  225.     return true;
  226.   }
  227. }
  228.  
  229.  
  230. static pq_item Xinsert(seq_item i, sw_point p) 
  231.   return X_structure->insert(i,p);
  232. }
  233.  
  234. static sw_point Xdelete(pq_item i) 
  235. {
  236.   sw_point p = X_structure->inf(i);
  237.   X_structure->del_item(i);
  238.   return p;
  239. }
  240.  
  241.  
  242. static node New_Node(GRAPH<point,int>& G,double x, double y )
  243. { return G.new_node(point(x,y)); }
  244.  
  245. static void New_Edge(GRAPH<point,int>& G,node v, node w, sw_segment l )
  246. { if (get_orient(l)==0)
  247.        G.new_edge(v,w,get_color(l));
  248.   else G.new_edge(w,v,get_color(l));
  249. }
  250.  
  251.  
  252. void vertical_segment(GRAPH<point,int>& SUB, sw_segment l)
  253.   sw_point p = new sw_POINT(get_x(get_startpoint(l)),get_y(get_startpoint(l)));
  254.   sw_point q = new sw_POINT(get_x(get_endpoint(l)),get_y(get_endpoint(l)));
  255.  
  256.   sw_point r = new sw_POINT(get_x(p)+1,get_y(p));
  257.   sw_point s = new sw_POINT(get_x(q)+1,get_y(q));
  258.  
  259.   sw_segment bot = new sw_SEGMENT(p,r,0,0);
  260.   sw_segment top = new sw_SEGMENT(q,s,0,0);
  261.  
  262.   seq_item bot_it = Y_structure->insert(bot,nil);
  263.   seq_item top_it = Y_structure->insert(top,nil);
  264.   seq_item sit;
  265.  
  266.   node u,v,w;
  267.   sw_segment seg;
  268.   
  269.  
  270.   for(sit=Y_structure->succ(bot_it); sit != top_it; sit=Y_structure->succ(sit))
  271.   { seg = Y_structure->key(sit);
  272.  
  273.     double cross_y = (get_slope(seg) * get_x(p) + get_yshift(seg));
  274.  
  275.     v = get_left_node(seg);
  276.     if (v==nil)
  277.     { w = New_Node(SUB,get_x(p),cross_y);
  278.       set_left_node(seg,w);
  279.      }
  280.     else
  281.     { double vx = SUB[v].xcoord();
  282.       if ( vx < get_x(p)-EPS2) 
  283.       { w = New_Node(SUB,get_x(p),cross_y);
  284.         New_Edge(SUB,v,w,seg);
  285.         set_left_node(seg,w);
  286.        }
  287.       else w = v;
  288.      }
  289.  
  290.     u = get_left_node(l);
  291.     if (u!=nil && u!=w) New_Edge(SUB,u,w,l);
  292.     set_left_node(l,w);
  293.  
  294.    }
  295.   
  296.   delete l;
  297.   delete top;
  298.   delete bot;
  299.     
  300.   Y_structure->del_item(bot_it);
  301.   Y_structure->del_item(top_it);
  302.  
  303.  }
  304.  
  305.  
  306. void Sweep_Segments(const list<segment>& L1, const list<segment>& L2, 
  307.                     GRAPH<point,int>& SUB,
  308.                     priority_queue<seq_item,sw_point>& Q,
  309.                     sortseq<sw_segment,pq_item>& S)
  310. {
  311.   sw_point    p,inter;
  312.   sw_segment  seg, l,lsit,lpred,lsucc,lpredpred;
  313.   pq_item  pqit,pxmin;
  314.   seq_item sitmin,sit,sitpred,sitsucc,sitpredpred;
  315.  
  316.   X_structure = &Q;
  317.   Y_structure = &S;
  318.  
  319.   int count=1;
  320.  
  321.   //initialization of the X-structure
  322.  
  323.   segment s;
  324.  
  325.   forall(s,L1) 
  326.    { sw_point p = new sw_POINT(s.start());
  327.      sw_point q = new sw_POINT(s.end());
  328.      seg = new sw_SEGMENT(p,q,0,count++);
  329.      Xinsert(nil,get_startpoint(seg));
  330.    }
  331.  
  332.   count = -1;
  333.  
  334.   forall(s,L2) 
  335.    { sw_point p = new sw_POINT(s.start());
  336.      sw_point q = new sw_POINT(s.end());
  337.      seg = new sw_SEGMENT(p,q,1,count--);
  338.      Xinsert(nil,get_startpoint(seg));
  339.    }
  340.  
  341.  
  342.   count = 0;
  343.  
  344.   x_sweep = -MAXINT;
  345.   y_sweep = -MAXINT;
  346.  
  347.  
  348.   while(!X_structure->empty())
  349.   {
  350.     pxmin = X_structure->find_min();
  351.     p = X_structure->inf(pxmin);
  352.  
  353.     sitmin = X_structure->key(pxmin);
  354.  
  355.     Xdelete(pxmin);
  356.  
  357.  
  358.  
  359.     if (get_kind(p) == Leftend)
  360.  
  361.     //left endpoint
  362.     { 
  363.  
  364.       l = get_seg(p); 
  365.  
  366.       x_sweep = get_x(p);
  367.       y_sweep = get_y(p);
  368.  
  369.  
  370.       if (get_x(p) == get_x(get_endpoint(l)))
  371.         vertical_segment(SUB,l);
  372.       else
  373.       {
  374.  
  375. /*
  376.       sit = Y_structure->lookup(l);
  377.       if (sit!=nil)  
  378.            error_handler(1,"plane sweep: sorry, overlapping segments");
  379. */
  380.  
  381.  
  382.       sit = Y_structure->insert(l,nil);
  383.  
  384.       Xinsert(sit,get_endpoint(l));
  385.  
  386.       sitpred = Y_structure->pred(sit);
  387.       sitsucc = Y_structure->succ(sit);
  388.  
  389.       if (sitpred != nil) 
  390.       { if ((pqit = Y_structure->inf(sitpred)) != nil)
  391.           delete Xdelete(pqit);
  392.  
  393.         lpred = Y_structure->key(sitpred);
  394.  
  395.         Y_structure->change_inf(sitpred,nil);
  396.  
  397.         if (intersection(lpred,l,inter))
  398.             Y_structure->change_inf(sitpred,Xinsert(sitpred,inter));
  399.       }
  400.  
  401.  
  402.       if (sitsucc != nil)
  403.       { lsucc = Y_structure->key(sitsucc);
  404.         if (intersection(lsucc,l,inter))
  405.            Y_structure->change_inf(sit,Xinsert(sit,inter));
  406.       }
  407.      } /* else if vertical */
  408.  
  409.     }
  410.     else if (get_kind(p) == Rightend)
  411.          //right endpoint
  412.          { 
  413.            x_sweep = get_x(p);
  414.            y_sweep = get_y(p);
  415.  
  416.            sit = sitmin;
  417.  
  418.            sitpred = Y_structure->pred(sit);
  419.            sitsucc = Y_structure->succ(sit);
  420.  
  421.            sw_segment seg = Y_structure->key(sit);
  422.  
  423.            Y_structure->del_item(sit);
  424.  
  425.            delete seg;
  426.  
  427.            if((sitpred != nil)&&(sitsucc != nil))
  428.            {
  429.              lpred = Y_structure->key(sitpred);
  430.              lsucc = Y_structure->key(sitsucc);
  431.              if (intersection(lsucc,lpred,inter))
  432.                 Y_structure->change_inf(sitpred,Xinsert(sitpred,inter));
  433.            }
  434.          }
  435.          else
  436.          /*point of intersection*/
  437.          { 
  438.            node w = New_Node(SUB,get_x(p),get_y(p));
  439.  
  440.            count++;
  441.  
  442.            /* Let L = list of all lines intersecting in p 
  443.  
  444.               we compute sit     = L.head();
  445.               and        sitpred = L.tail();
  446.  
  447.               by scanning the Y_structure in both directions 
  448.               starting at sitmin;
  449.  
  450.            */
  451.  
  452.            /* search for sitpred upwards from sitmin: */
  453.  
  454.            Y_structure->change_inf(sitmin,nil);
  455.  
  456.            sitpred = Y_structure->succ(sitmin);
  457.  
  458.  
  459.            while ((pqit=Y_structure->inf(sitpred)) != nil)
  460.            { sw_point q = X_structure->inf(pqit);
  461.              if (compare(p,q) != 0) break; 
  462.              X_structure->del_item(pqit);
  463.              Y_structure->change_inf(sitpred,nil);
  464.              sitpred = Y_structure->succ(sitpred);
  465.             }
  466.  
  467.  
  468.            /* search for sit downwards from sitmin: */
  469.  
  470.            sit = sitmin;
  471.  
  472.            seq_item sit1;
  473.            
  474.            while ((sit1=Y_structure->pred(sit)) != nil)
  475.            { pqit = Y_structure->inf(sit1);
  476.              if (pqit == nil) break;
  477.              sw_point q = X_structure->inf(pqit);
  478.              if (compare(p,q) != 0) break; 
  479.              X_structure->del_item(pqit);
  480.              Y_structure->change_inf(sit1,nil);
  481.              sit = sit1;
  482.             }
  483.  
  484.  
  485.  
  486.            // insert edges to p for all sw_segments in sit, ..., sitpred into SUB
  487.            // and set left node to w 
  488.  
  489.            lsit = Y_structure->key(sitpred);
  490.  
  491.            node v = get_left_node(lsit);
  492.            if (v!=nil) New_Edge(SUB,v,w,lsit);
  493.            set_left_node(lsit,w);
  494.  
  495.            for(sit1=sit; sit1!=sitpred; sit1 = Y_structure->succ(sit1))
  496.            { lsit = Y_structure->key(sit1);
  497.  
  498.              v = get_left_node(lsit);
  499.              if (v!=nil) New_Edge(SUB,v,w,lsit);
  500.              set_left_node(lsit,w);
  501.             }
  502.  
  503.            lsit = Y_structure->key(sit);
  504.            lpred=Y_structure->key(sitpred);
  505.            sitpredpred = Y_structure->pred(sit);
  506.            sitsucc=Y_structure->succ(sitpred);
  507.  
  508.  
  509.            if (sitpredpred != nil)
  510.             { 
  511.               lpredpred=Y_structure->key(sitpredpred);
  512.  
  513.               if ((pqit = Y_structure->inf(sitpredpred)) != nil)
  514.                 delete Xdelete(pqit);
  515.  
  516.               Y_structure->change_inf(sitpredpred,nil);
  517.  
  518.  
  519.               if (intersection(lpred,lpredpred,inter))
  520.                 Y_structure->change_inf(sitpredpred,
  521.                                        Xinsert(sitpredpred,inter));
  522.              }
  523.  
  524.  
  525.            if (sitsucc != nil)
  526.             {
  527.               lsucc=Y_structure->key(sitsucc);
  528.  
  529.               if ((pqit = Y_structure->inf(sitpred)) != nil)
  530.                 delete Xdelete(pqit);
  531.                  
  532.               Y_structure->change_inf(sitpred,nil);
  533.  
  534.               if (intersection(lsucc,lsit,inter))
  535.                   Y_structure->change_inf(sit,Xinsert(sit,inter));
  536.              }
  537.  
  538.  
  539. // reverse the subsequence sit, ... ,sitpred  in the Y_structure
  540.  
  541.            x_sweep = get_x(p);
  542.            y_sweep = get_y(p);
  543.  
  544.            Y_structure->reverse_items(sit,sitpred);
  545.  
  546.           delete p;
  547.  
  548.          } // intersection
  549.  
  550.   }
  551.  
  552.   X_structure->clear();
  553.  
  554. }
  555.  
  556.  
  557.  
  558. #if !defined(__TEMPLATE_ARGS_AS_BASE__)
  559. declare3(_sortseq,sw_segment,pq_item,skiplist)
  560. declare3(_sortseq,sw_segment,pq_item,ab_tree)
  561. #endif
  562.  
  563. main()
  564.   int N = read_int("N = ");
  565.  
  566.   list<segment> seglist1,seglist2;
  567.   
  568.   while (N--) 
  569.   { double x1 = random(-1000,-100);
  570.     double y1 = random(-1000,1000);
  571.     double x2 = random(100,1000);
  572.     double y2 = random(-1000,1000);
  573.     seglist1.append(segment(x1,y1,x2,y2));
  574.    }
  575.  
  576.   GRAPH<point,int> SUB;
  577.  
  578.   sortseq<sw_segment,pq_item>           rst_seq;
  579.  
  580. #if defined(__TEMPLATE_ARGS_AS_BASE__)
  581.   _sortseq<sw_segment,pq_item,ab_tree>   abt_seq;
  582.   _sortseq<sw_segment,pq_item,skiplist>  skip_seq;
  583. #else
  584.   _sortseq(sw_segment,pq_item,ab_tree)   abt_seq;
  585.   _sortseq(sw_segment,pq_item,skiplist)  skip_seq;
  586. #endif
  587.  
  588.   priority_queue<seq_item,sw_point>     Q;
  589.  
  590.  
  591.   float T;
  592.  
  593.   T = used_time();
  594.   cout << "SWEEP_SEGMENTS: ";
  595.   cout.flush(); 
  596.   SWEEP_SEGMENTS(seglist1,seglist2,SUB);
  597.   cout<< string(" # = %d time = %6.2f sec",SUB.number_of_nodes(), used_time(T));
  598.   newline;
  599.  
  600.   SUB.clear();
  601.  
  602.   T = used_time();
  603.   cout << "rs_tree:        ";
  604.   cout.flush(); 
  605.   Sweep_Segments(seglist1,seglist2,SUB,Q,rst_seq);
  606.   cout<< string(" # = %d time = %6.2f sec",SUB.number_of_nodes(), used_time(T));
  607.   newline;
  608.  
  609.   SUB.clear();
  610.  
  611.   T = used_time();
  612.   cout << "ab_tree:        ";
  613.   cout.flush(); 
  614.   Sweep_Segments(seglist1,seglist2,SUB,Q,abt_seq);
  615.   cout<< string(" # = %d time = %6.2f sec",SUB.number_of_nodes(), used_time(T));
  616.   newline;
  617.  
  618.   SUB.clear();
  619.  
  620.   T = used_time();
  621.   cout << "skiplist:       ";
  622.   cout.flush(); 
  623.   Sweep_Segments(seglist1,seglist2,SUB,Q,skip_seq);
  624.   cout<< string(" # = %d time = %6.2f sec",SUB.number_of_nodes(), used_time(T));
  625.   newline;
  626.  
  627. return 0;
  628.  
  629. }
  630.